home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…stman Always Clicks Twice / ADC Developer CD (1993-01) (''The Postman Always Clicks Twice'')_iso / Dev.CD 199301.iso / Technical Documentation / Sample Code / DTS.Lib & Samples / DTS.Lib / AEConnect.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-22  |  20.1 KB  |  608 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** Program:        DTS.Lib
  5. ** File:        AEConnect.c
  6. ** Written by:  Eric Soldan
  7. **
  8. ** Copyright © 1990-1991 Apple Computer, Inc.
  9. ** All rights reserved.
  10. **
  11. ** This is the custom AppleEvents code used for establishing a connection
  12. ** to another window.  DTS.Lib targets a specific window in an application,
  13. ** not just an application.  It also sends and returns more information
  14. ** about the connection, such as user name, zone, and machine.  This
  15. ** information is two-way, so each user can know who they are connected to.
  16. */
  17.  
  18.  
  19.  
  20. /*****************************************************************************/
  21.  
  22.  
  23.  
  24. #include "DTS.Lib2.h"
  25. #include "DTS.Lib.Common.h"
  26. #include "DTS.Lib.protos.h"
  27.  
  28. #ifndef __RESOURCES__
  29. #include <Resources.h>
  30. #endif
  31.  
  32. #ifndef THINK_C
  33. #ifndef __SYSEQU__
  34. #include <SysEqu.h>
  35. #endif
  36. #endif
  37.  
  38. #ifndef __TOOLUTILS__
  39. #include <ToolUtils.h>
  40. #endif
  41.  
  42. #include "Utilities.h"
  43.  
  44.  
  45.  
  46. /*****************************************************************************/
  47.  
  48.  
  49.  
  50. extern OSType        gDocCreator;
  51. extern short        gMinVersion, gMaxVersion;
  52. extern Boolean        gHasAppleEvents;
  53. extern Cursor        *gCursorPtr;
  54.  
  55. static pascal OSErr        DoAEAnswer(AppleEvent *message, AppleEvent *reply, long refcon);
  56. static pascal OSErr        ReceiveConnect(AppleEvent *message, AppleEvent *reply, long refcon);
  57. static pascal OSErr        ReceiveConnectReply(AppleEvent *message, AppleEvent *reply);
  58. static pascal Boolean    AEPortFilter(LocationNamePtr locationName, PortInfoPtr thePortInfo);
  59.  
  60.  
  61.  
  62. /*****************************************************************************/
  63.  
  64.  
  65.  
  66. static AEHandler keywordsToInstall[] = {
  67.     { kCoreEventClass,        kAEAnswer,            (ProcPtr)DoAEAnswer },
  68.     { kCustomEventClass,    keyAppConnect,        (ProcPtr)ReceiveConnect },
  69. };        /* These are the custom AppleEvents. */
  70.  
  71.  
  72.  
  73. /*****************************************************************************/
  74. /*****************************************************************************/
  75.  
  76.  
  77.  
  78. /* Install the AppleEvents we use to establish a connection to a specific
  79. ** window.  This is done in addition to installing the required AppleEvents.
  80. ** InitAppleEvents, which installs the required AppleEvents, must be called
  81. ** first, since it sets up some global values. */
  82.  
  83. #pragma segment AppleEvents
  84. void    InitConnectAppleEvents(void)
  85. {
  86.     OSErr    err;
  87.     short    i;
  88.  
  89.     if (gHasAppleEvents) {
  90.         for (i = 0; i < (sizeof(keywordsToInstall) / sizeof(AEHandler)); ++i) {
  91.             err = AEInstallEventHandler(
  92.                 keywordsToInstall[i].theEventClass,    /* What class to install.  */
  93.                 keywordsToInstall[i].theEventID,    /* Keywords to install.    */
  94.                 keywordsToInstall[i].theHandler,    /* The AppleEvent handler. */
  95.                 0L,                                    /* Unused refcon.           */
  96.                 false                                /* Only for our app.       */
  97.             );
  98.  
  99.             if (err) {
  100.                 HCenteredAlert(rErrorAlert, nil, (ModalFilterProcPtr)AlertFilter);
  101.                 return;
  102.             }
  103.         }
  104.     }
  105. }
  106.  
  107.  
  108.  
  109. /*****************************************************************************/
  110.  
  111.  
  112.  
  113. /* This function handles the connect reply.  DTS.framework sends the connect request
  114. ** via kAEQueueReply.  This means that it doesn't necessarily come back immediately.
  115. ** (It actually comes back right away if it is connected to itself.)  The reply
  116. ** normally comes in via a high-level event.  Until this reply comes in, the
  117. ** connection isn't established.  When this reply does come in, the remaining
  118. ** information necessary to establish the connection to a particular window in
  119. ** the target application is recorded. */
  120.  
  121. #pragma segment AppleEvents
  122. static pascal OSErr    DoAEAnswer(AppleEvent *message, AppleEvent *reply, long refcon)
  123. {
  124. #pragma unused (refcon)
  125.  
  126.     gCursorPtr = nil;        /* Force re-calc of cursor region and cursor to use. */
  127.     return(ReceiveConnectReply(message, reply));
  128. }
  129.  
  130.  
  131.  
  132. /*****************************************************************************/
  133.  
  134.  
  135.  
  136. /* This is the function that is called to establish a connection to another
  137. ** DTS.framework-based application.  The "other" DTS.framework-based application is probably
  138. ** the same application on another machine.  This code does a bit more than simply connecting
  139. ** to another application.  It targets a specific window within that application.  It doesn't
  140. ** just target zone/machine/application, which is the granularity that AppleEvents gives you.
  141. ** It also passes back and forth some information that is kind of a pain to get, but
  142. ** is nice to have.  One such piece of information is the user name.  This needs to be
  143. ** sent.  It can't be determined from the message from an AppleEvent.  The sender sends
  144. ** the user name, and the receiver returns the remote user name.  The user name is
  145. ** placed in the document record for the window to be used if you wish. */
  146.  
  147. #pragma segment AppleEvents
  148. OSErr    SendConnect(FileRecHndl frHndl, char *theLocNBPType)
  149. {
  150.     AEAddressDesc    remoteLoc;
  151.     OSErr            err;
  152.     long            windTag[2], size;
  153.     char            hstate;
  154.     Ptr                ptr1, ptr2;
  155.     AppleEvent        theAevt, reply;
  156.     Str255            macText, appText;
  157.     Str32            remoteName;
  158.     Handle            remoteNameHndl;
  159.     OSType            sftype;
  160.     FSSpec            myFSS;
  161.  
  162.     theAevt.dataHandle = reply.dataHandle = nil;
  163.         /* Make sure disposing of the descriptors is okay in all cases.
  164.         ** theAevt and reply aren't necessarily instantiated correctly, so
  165.         ** we need to make sure that the dispose is safe, even if they aren't
  166.         ** valid.  theAevt isn't valid if MakeTarget returns an error.  If
  167.         ** MakeTarget returns an error, then AECreateAppleEvent isn't called
  168.         ** for theAevt.  Similarly, if AESend isn't called, reply isn't valid. */
  169.  
  170.     GetIndString(macText, rPPCText, sTitleText);
  171.     GetIndString(appText, rPPCText, sAppText);
  172.  
  173.     err = MakeTarget(&remoteLoc, false, kAEWaitReply, macText, appText,
  174.                     (PPCFilterProcPtr)AEPortFilter, theLocNBPType);
  175.         /* Generate the target for the remote user. */
  176.  
  177.     (*frHndl)->connect.remoteLoc    = remoteLoc;
  178.     (*frHndl)->connect.windowTag[0] = windTag[0] = (TickCount() & 0xFFFFFFFE);
  179.     (*frHndl)->connect.windowTag[1] = windTag[0];
  180.         /* The windTag fields are used to determine which window is the target
  181.         ** for an incomming AppleEvent.  windTag[0] for the application doing
  182.         ** the connecting will be even, and windTag[1] (the target's ID) will
  183.         ** be odd.  This prevents any accidental occurance where the windTag
  184.         ** fields are the same.  The target application will store these values
  185.         ** reversed.  Any incomming AppleEvent, from either application, will
  186.         ** invert these fields and then scan the window list looking for a window
  187.         ** that has the correct values in these fields.  If there is no such
  188.         ** window, then the window was closed at some point.  Initially, the sender
  189.         ** sets these values to be the same.  Until the sender receives a return
  190.         ** reply for the connect message, the windows aren't officially connected.
  191.         ** When the reply comes in, then the windTag[1] field is set to the reply's
  192.         ** return value. */
  193.  
  194.     if (!err) {        /* Create the AppleEvent... */
  195.         err = AECreateAppleEvent(        /* Create empty AppleEvent.       */
  196.             kCustomEventClass,            /*   Event class.               */
  197.             typeAppConnect,                /*   Event ID.                   */
  198.             &remoteLoc,                    /*   Address of receiving app. */
  199.             kAutoGenerateReturnID,        /*   This value causes the       */
  200.                                         /*   AppleEvent manager to       */
  201.                                         /*   assign a return ID that   */
  202.                                         /*   is unique to the session. */
  203.             kAnyTransactionID,            /*   Ignore transaction ID.       */
  204.             &theAevt                    /*   Location of event.           */
  205.         );
  206.     }
  207.  
  208.     if (!err) {
  209.         sftype = (*frHndl)->fileState.sfType;
  210.         err = AEPutParamPtr(    /* Add document type to AppleEvent. */
  211.             &theAevt,            /*   AppleEvent to add to. */
  212.             keySFType,            /*   AEKeyword.               */
  213.             typeLongInteger,    /*   Actual type.           */
  214.             (Ptr)&sftype,        /*   Pointer to the data.  */
  215.             sizeof(OSType)        /*   Size of the data.       */
  216.         );
  217.     }
  218.  
  219.     if (!err) {
  220.         myFSS = (*frHndl)->fileState.fss;
  221.         err = AEPutParamPtr(    /* Add document name (which is in the FSSpec) to AppleEvent. */
  222.             &theAevt,            /*   AppleEvent to add to. */
  223.             keyFSS,                /*   AEKeyword.               */
  224.             typeFSS,            /*   Desired type.           */
  225.             (Ptr)&myFSS,        /*   Pointer to the data.  */
  226.             sizeof(FSSpec)        /*   Size of the data.       */
  227.         );
  228.     }
  229.  
  230.     if (!err) {
  231.         hstate = HGetState((Handle)frHndl);
  232.         HLock((Handle)frHndl);
  233.         ptr1   = (Ptr)&((*frHndl)->connect);
  234.         ptr2   = (Ptr)&((*frHndl)->connect.endSendInfo);
  235.         size   = (long)ptr2 - (long)ptr1;
  236.         err = AEPutParamPtr(    /* Add file connect info to the AppleEvent. */
  237.             &theAevt,            /*   AppleEvent to add to.             */
  238.             keyAppConnect,        /*   AEKeyword.                         */
  239.             typeAppConnect,        /*   Desired type.                     */
  240.             ptr1,                /*   Pointer to the data to be sent. */
  241.             size                /*   Size of the data to be sent.     */
  242.         );
  243.         HSetState((Handle)frHndl, hstate);
  244.     }
  245.  
  246.     if (!err) {
  247.         remoteName[0] = 0;
  248.         if (remoteNameHndl = GetResource('STR ', -16096))
  249.             pcpy(remoteName, (StringPtr)(*remoteNameHndl));
  250.         err = AEPutParamPtr(    /* Add user name to AppleEvent. */
  251.             &theAevt,            /*   AppleEvent to add to. */
  252.             keyPascal,            /*   AEKeyword.               */
  253.             typePascal,            /*   Desired type.           */
  254.             (Ptr)remoteName,    /*   Pointer to the data.  */
  255.             remoteName[0] + 1    /*   Size of the data.       */
  256.         );
  257.     }
  258.  
  259.     if (!err) {        /* If we have an AppleEvent ready to send... */
  260.         err = AESend(            /* Send AppleEvent.              */
  261.             &theAevt,            /*   Our Apple Event to send. */
  262.             &reply,                /*   We may have a reply.      */
  263.             kAEQueueReply,        /*   Type of reply.              */
  264.             kAENormalPriority,    /*   App. send priority.      */
  265.             0,                    /*   We aren't waiting.          */
  266.             nil,                /*   We aren't waiting.          */
  267.             nil                    /*   EventFilterProcPtr.      */
  268.         );
  269.     }
  270.     if (remoteLoc.descriptorType == typeProcessSerialNumber)
  271.         err = ReceiveConnectReply(&reply, &reply);
  272.             /* If we want a queue reply, and if we are sending to ourselves,
  273.             ** then we already have the reply.  Since we are sending to
  274.             ** ourselves, everything happens right away, even for queue reply, so
  275.             ** we must handle the connect reply here.  If we are sending to another
  276.             ** machine, then the reply will come in as a high-level event and we
  277.             ** will process it through the event loop. */
  278.  
  279.     AEDisposeDesc(&theAevt);
  280.     AEDisposeDesc(&reply);
  281.         /* Dispose of the descriptors, created or not.
  282.         ** If not created, no harm done by calling. */
  283.  
  284.     if (err) {
  285.         AEDisposeDesc(&remoteLoc);
  286.             /* If we didn't connect, get rid of the target descriptor.  If we
  287.             ** succeeded at connecting, then we keep the descriptor until the
  288.             ** connection is broken by the application. */
  289.  
  290.         (*frHndl)->connect.windowTag[0] = 0;
  291.         (*frHndl)->connect.windowTag[1] = 0;
  292.             /* Mark this window so that it will never be found if we somehow
  293.             ** do get an answer from the receiver, even after failure. */
  294.     }
  295.  
  296.     return(err);
  297. }
  298.  
  299.  
  300.  
  301. /*****************************************************************************/
  302.  
  303.  
  304.  
  305. /* This function receives a connect message from SendConnect.  The connection
  306. ** tasks that the receiver has to do are done here, such as opening a window for
  307. ** this end of the connection, etc.  It also returns whether or not it succeeded,
  308. ** and the user name.  Basically, it establishes the connection, while keeping
  309. ** some data as to whom it is connected to. */
  310.  
  311. #pragma segment AppleEvents
  312. static pascal OSErr    ReceiveConnect(AppleEvent *message, AppleEvent *reply, long refcon)
  313. {
  314. #pragma unused (refcon)
  315.  
  316.     OSErr            err;
  317.     FileRecHndl        frHndl;
  318.     char            hstate;
  319.     Ptr                ptr1, ptr2;
  320.     long            size, windTag[2];
  321.     AEAddressDesc    senderTarget;
  322.     DescType        ignoredType;
  323.     Size            ignoredSize;
  324.     OSType            sftype;
  325.     FSSpec            myFSS;
  326.     Str32            remoteZone, remoteMachine, remoteApplication, remoteName;
  327.     Handle            remoteNameHndl;
  328.     short            vers;
  329.  
  330.     err = AEGetParamPtr(    /* Get OSType to determine document type. */
  331.         message,            /*   The AppleEvent.            */
  332.         keySFType,            /*   AEKeyword                   */
  333.         typeLongInteger,    /*   Desired type.               */
  334.         &ignoredType,        /*   Type code.                   */
  335.         (Ptr)&sftype,        /*   Pointer to area for data. */ 
  336.         sizeof(OSType),        /*   Size of the data.           */
  337.         &ignoredSize        /*   Returned size of data.       */
  338.     );
  339.  
  340.     if (!err)
  341.         err = NewDocument(&frHndl, sftype, false);
  342.  
  343.     if (err) return(err);
  344.  
  345.     if (!err) {
  346.         hstate = HGetState((Handle)frHndl);
  347.         HLock((Handle)frHndl);
  348.         ptr1   = (Ptr)&((*frHndl)->connect);
  349.         ptr2   = (Ptr)&((*frHndl)->connect.endSendInfo);
  350.         size   = (long)ptr2 - (long)ptr1;
  351.         err = AEGetParamPtr(    /* Get connect info from the AppleEvent. */
  352.             message,            /*   The AppleEvent.            */
  353.             keyAppConnect,        /*   AEKeyword                   */
  354.             typeAppConnect,        /*   Desired type.               */
  355.             &ignoredType,        /*   Type code.                   */
  356.             ptr1,                /*   Pointer to area for data. */ 
  357.             size,                /*   Size of data area.           */
  358.             &ignoredSize        /*   Returned size of data.       */
  359.         );
  360.         HSetState((Handle)frHndl, hstate);
  361.     }
  362.  
  363.     if (!err) {
  364.         err = AEGetAttributeDesc(    /* Get address of sender.     */
  365.             message,                /*   Get address of sender from message. */
  366.             keyAddressAttr,            /*   We want an address.                 */
  367.             typeWildCard,            /*   We want the address of the sender.     */
  368.             &senderTarget            /*   Address of sender.                     */
  369.         );
  370.         if (!err) {
  371.             (*frHndl)->connect.remoteLoc = senderTarget;
  372.             err = AEGetParamPtr(    /* Get FSSpec (for document name) from AppleEvent. */
  373.                 message,            /*   The AppleEvent.            */
  374.                 keyFSS,                /*   AEKeyword                   */
  375.                 typeFSS,            /*   Desired type.               */
  376.                 &ignoredType,        /*   Type code.                   */
  377.                 (Ptr)&myFSS,        /*   Pointer to area for data. */ 
  378.                 sizeof(FSSpec),        /*   Size of the data.           */
  379.                 &ignoredSize        /*   Returned size of data.       */
  380.             );
  381.             if (!err)
  382.                 pcpy((*frHndl)->fileState.fss.name, (StringPtr)myFSS.name);
  383.         }
  384.         if (!err) {
  385.             err = AEGetParamPtr(    /* Get user name from AppleEvent. */
  386.                 message,            /*   The AppleEvent.            */
  387.                 keyPascal,            /*   AEKeyword                   */
  388.                 typePascal,            /*   Desired type.               */
  389.                 &ignoredType,        /*   Type code.                   */
  390.                 (Ptr)remoteName,    /*   Pointer to area for data. */ 
  391.                 sizeof(Str255),        /*   Size of the data.           */
  392.                 &ignoredSize        /*   Returned size of data.       */
  393.             );
  394.             (*frHndl)->connect.remoteName[0] = 0;
  395.             if (!err) {
  396.                 pcpy((*frHndl)->connect.remoteName, remoteName);
  397.                 remoteZone[0] = remoteMachine[0] = 0;
  398.                 GetTargetInfo(senderTarget, remoteZone, remoteMachine, remoteApplication);
  399.                 pcpy((*frHndl)->connect.remoteZone, remoteZone);
  400.                 pcpy((*frHndl)->connect.remoteMachine, remoteMachine);
  401.             }
  402.         }
  403.     }
  404.  
  405.     if (!err) {        /* If we got the remote user address... */
  406.  
  407.         (*frHndl)->connect.windowTag[0] = windTag[0] = (TickCount() | 0x01);
  408.         (*frHndl)->connect.connected = true;
  409.  
  410.         vers = (*frHndl)->d.doc.fhInfo.version;
  411.         if ((vers < gMinVersion) || (vers > gMaxVersion))
  412.             err = errAEWrongDataType;
  413.                 /* Incompatible file format. */
  414.  
  415.         if (!err) {
  416.             windTag[1] = (*frHndl)->connect.windowTag[1];
  417.             err = AEPutParamPtr(    /* Return receiver window ID. */
  418.                 reply,                /*   The AppleEvent.            */
  419.                 keyWindowTag,        /*   AEKeyword                   */
  420.                 typeDoubleLong,        /*   Type code.                   */
  421.                 (Ptr)&windTag[0],    /*   Pointer to area for data. */ 
  422.                 2 * sizeof(long)    /*   Size of data area.           */
  423.             );
  424.         }
  425.  
  426.         if (!err) {
  427.             remoteName[0] = 0;
  428.             if (remoteNameHndl = GetResource('STR ', -16096))
  429.                 pcpy(remoteName, (StringPtr)(*remoteNameHndl));
  430.             err = AEPutParamPtr(    /* Return receiver user name. */
  431.                 reply,                /*   The AppleEvent.            */
  432.                 keyPascal,            /*   AEKeyword                   */
  433.                 typePascal,            /*   Type code.                   */
  434.                 (Ptr)remoteName,    /*   Pointer to area for data. */ 
  435.                 remoteName[0] + 1    /*   Size of data area.           */
  436.             );
  437.         }
  438.  
  439.         if (!err)
  440.             err = DoNewWindow(frHndl, nil, FrontWindow(), (WindowPtr)-1);
  441.                 /* If connecting worked, create a window for the document. */
  442.     }
  443.  
  444.     if (err)
  445.         DisposeDocument(frHndl);
  446.  
  447.     if (!err)
  448.         NotifyUser();
  449.  
  450.     return(err);
  451. }
  452.  
  453.  
  454.  
  455. /*****************************************************************************/
  456.  
  457.  
  458.  
  459. /* This function is called when you want to determine which window an AppleEvent
  460. ** is targeted for.  DTS.framework AppleEvents send two long values along with the AppleEvent
  461. ** to determine which window is the target window.  One of the longs is an ID for the
  462. ** sender, and the other is an ID for the receiver.  When a connection is established,
  463. ** these values are saved for both the sender and the receiver.  This allows the
  464. ** AppleEvent to be sent in either direction and still be targeted to the correct window.
  465. ** To find which window is the target, get these two longs out of the AppleEvent and then
  466. ** call GetAEWindow.  The first value is always the ID of the machine itself, and the
  467. ** second value is always the ID of the remote machine.  Due to this, you will need to
  468. ** reverse the order of these ID's for incomming DTS.framework AppleEvents. */
  469.  
  470. #pragma segment AppleEvents
  471. static pascal OSErr    ReceiveConnectReply(AppleEvent *message, AppleEvent *reply)
  472. {
  473. #pragma unused (reply)
  474.  
  475.     OSErr            err, replyErr;
  476.     DescType        actualType;
  477.     long            windTag[2], actualSize;
  478.     WindowPtr        window;
  479.     FileRecHndl        frHndl;
  480.     Str32            remoteZone, remoteMachine, remoteApplication, remoteName;
  481.  
  482.     err = AEGetParamPtr(        /* Check for a receiver error... */
  483.         message,                /*   The AppleEvent.            */
  484.         keyReplyErr,            /*   AEKeyword                   */
  485.         typeShortInteger,        /*   Desired type.               */
  486.         &actualType,            /*   Type code.                   */
  487.         (Ptr)&replyErr,            /*   Pointer to area for data. */ 
  488.         sizeof(short),            /*   Size of data area.           */
  489.         &actualSize                /*   Returned size of data.       */
  490.     );
  491.     if (err == errAEDescNotFound)
  492.         err = noErr;
  493.     else
  494.         if (!err)
  495.             err = replyErr;
  496.  
  497.     if (!err) {
  498.         err = AEGetParamPtr(    /* Get receiver window ID. */
  499.             message,            /*   The AppleEvent.            */
  500.             keyWindowTag,        /*   AEKeyword                   */
  501.             typeDoubleLong,        /*   Desired type.               */
  502.             &actualType,        /*   Type code.                   */
  503.             (Ptr)&windTag[0],    /*   Pointer to area for data. */ 
  504.             2 * sizeof(long),    /*   Size of data area.           */
  505.             &actualSize            /*   Returned size of data.       */
  506.         );
  507.     }
  508.  
  509.     if (!err) {        /* If we got the receiver window ID... */
  510.  
  511.         window = GetAEWindow(windTag[1], windTag[1]);
  512.             /* The ID's are still both ours, since this is where we
  513.             ** get the receiver's ID returned.  windTag[0] holds the
  514.             ** receiver's ID, and windTag[1] holds ours. */
  515.  
  516.         if (window) {
  517.             frHndl = (FileRecHndl)GetWRefCon(window);
  518.             if (!(*frHndl)->connect.connected) {
  519.                 err = AEGetParamPtr(
  520.                     message,            /* The AppleEvent.              */
  521.                     keyPascal,            /* AEKeyword                 */
  522.                     typePascal,            /* Desired type.             */
  523.                     &actualType,        /* Type code.                 */
  524.                     (Ptr)remoteName,    /* Pointer to area for data. */ 
  525.                     sizeof(Str255),        /* Size of data area.         */
  526.                     &actualSize            /* Returned size of data.     */
  527.                 );
  528.  
  529.                 (*frHndl)->connect.remoteName[0] = 0;
  530.                 if (!err) {        /* Connection is for sure, so remember what we need. */
  531.                     (*frHndl)->connect.windowTag[1] = windTag[0];
  532.                     pcpy((*frHndl)->connect.remoteName, remoteName);
  533.                     GetTargetInfo((*frHndl)->connect.remoteLoc,
  534.                                   remoteZone, remoteMachine, remoteApplication);
  535.                     pcpy((*frHndl)->connect.remoteZone, remoteZone);
  536.                     pcpy((*frHndl)->connect.remoteMachine, remoteMachine);
  537.                     (*frHndl)->connect.connected = true;
  538.                 }
  539.                 else
  540.                     (*frHndl)->connect.windowTag[0] = (*frHndl)->connect.windowTag[1] = 0;
  541.             }
  542.         }
  543.     }
  544.  
  545.     return(err);
  546. }
  547.  
  548.  
  549.  
  550. /*****************************************************************************/
  551.  
  552.  
  553.  
  554. /* Find the window with the specified window ID's. */
  555.  
  556. #pragma segment AppleEvents
  557. WindowPtr    GetAEWindow(long windTag_0, long windTag_1)
  558. {
  559.     WindowPeek    window;
  560.     FileRecHndl    frHndl;
  561.  
  562. #ifdef __SYSEQU__
  563.     for (window = *(WindowPeek *)WindowList; window; window = window->nextWindow) {
  564. #else
  565.     for (window = (WindowPeek)WindowList; window; window = window->nextWindow) {
  566. #endif
  567.         if (IsAppWindow((WindowPtr)window)) {
  568.             frHndl = (FileRecHndl)GetWRefCon((WindowPtr)window);
  569.             if (
  570.                 ((*frHndl)->connect.windowTag[0] == windTag_0) &&
  571.                 ((*frHndl)->connect.windowTag[1] == windTag_1)
  572.             ) return((WindowPtr)window);
  573.         }
  574.     }
  575.  
  576.     return(nil);
  577. }
  578.  
  579.  
  580.  
  581. /*****************************************************************************/
  582.  
  583.  
  584.  
  585. /* This function doesn't allow the PPCBrowser to display any applications other
  586. ** than the designated application(s). */
  587.  
  588. #pragma segment AppleEvents
  589. static pascal Boolean    AEPortFilter(LocationNamePtr locationName, PortInfoPtr thePortInfo)
  590. {
  591. #pragma unused (locationName)
  592.  
  593.     OSType    type;
  594.  
  595.     if (thePortInfo->name.portKindSelector == ppcByString) {
  596.         BlockMove(thePortInfo->name.u.portTypeStr + 1, (Ptr)&type, 4);
  597.             /* The BlockMove is so that we don't get an address error
  598.             ** on a 68000-based machine due to referencing a long at
  599.             ** an odd-address. */
  600.         if (type == gDocCreator) return(true);
  601.     }
  602.  
  603.     return(false);
  604. }
  605.  
  606.  
  607.  
  608.